﻿//
// (C) Copyright 2009 Irantha Suwandarathna (iranthas@hotmail.com)
// All rights reserved.
//

/* Copyright (c) 2001-2008, The HSQL Development Group
 * All rights reserved.
 *
 * Redistribution and use _in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * Redistributions _in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer _in the documentation
 * and/or other materials provided with the distribution.
 *
 * Neither the name of the HSQL Development Group nor the names of its
 * contributors may be used to endorse or promote products derived from this
 * software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace EffiProz.Core.Lib
{
    public abstract class BaseList
    {
        protected int elementCount;

        public abstract Object get(int index);

        public abstract Object remove(int index);

        public abstract bool add(Object o);

        public abstract int size();

        public bool contains(Object o)
        {
            return indexOf(o) == -1 ? false
                                 : true;
        }

        public bool remove(Object o)
        {

            int i = indexOf(o);

            if (i == -1)
            {
                return false;
            }

            remove(i);

            return true;
        }

        public virtual int indexOf(Object o)
        {

            for (int i = 0, _size = size(); i < _size; i++)
            {
                Object current = get(i);

                if (current == null)
                {
                    if (o == null)
                    {
                        return i;
                    }
                }
                else if (current.Equals(o))
                {
                    return i;
                }
            }

            return -1;
        }

        public bool addAll(Collection other)
        {

            bool result = false;
            Iterator it = other.iterator();

            while (it.hasNext())
            {
                result = true;

                add(it.next());
            }

            return result;
        }

        public bool addAll(Object[] array)
        {

            bool result = false;
            for (int i = 0; i < array.Length; i++)
            {
                result = true;

                add(array[i]);
            }

            return result;
        }

        public virtual bool isEmpty()
        {
            return elementCount == 0;
        }

        /** Returns a string representation */
        public String toString()
        {

            StringBuilder sb = new StringBuilder(32 + elementCount * 3);

            sb.Append("List : size=");
            sb.Append(elementCount);
            sb.Append(' ');
            sb.Append('{');

            Iterator it = iterator();

            while (it.hasNext())
            {
                sb.Append(it.next());

                if (it.hasNext())
                {
                    sb.Append(',');
                    sb.Append(' ');
                }
            }

            sb.Append('}');

            return sb.ToString();
        }

        public Iterator iterator()
        {
            return new BaseListIterator(this);
        }

        private class BaseListIterator : Iterator
        {

            int counter = 0;
            bool removed;
            BaseList _o;

            public BaseListIterator(BaseList _o)
            {
                this._o = _o;
            }

            public bool hasNext()
            {
                return counter < _o.elementCount;
            }

            public Object next()
            {

                if (counter < _o.elementCount)
                {
                    removed = false;

                    Object returnValue = _o.get(counter);

                    counter++;

                    return returnValue;
                }

                throw new KeyNotFoundException();
            }

            public int nextInt()
            {
                throw new KeyNotFoundException();
            }

            public long nextLong()
            {
                throw new KeyNotFoundException();
            }

            public void remove()
            {

                if (removed)
                {
                    throw new KeyNotFoundException("Iterator");
                }

                removed = true;

                if (counter != 0)
                {
                    _o.remove(counter - 1);

                    counter--;    // above can throw, so decrement if successful

                    return;
                }

                throw new KeyNotFoundException();
            }

            public void setValue(Object value)
            {
                throw new KeyNotFoundException();
            }
        }

    }
}
